// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h"

#include <string.h>
#include <windows.h>

#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_hdc.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/proxy/serialized_structs.h"

namespace content {

namespace {

    typedef std::vector<std::string> FontFamilyList;
    typedef std::vector<ppapi::proxy::SerializedTrueTypeFontDesc> FontDescList;

    static int CALLBACK EnumFontFamiliesProc(ENUMLOGFONTEXW* logical_font,
        NEWTEXTMETRICEXW* physical_font,
        DWORD font_type,
        LPARAM lparam)
    {
        FontFamilyList* font_families = reinterpret_cast<FontFamilyList*>(lparam);
        if (font_families) {
            const LOGFONTW& lf = logical_font->elfLogFont;
            if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@' && lf.lfOutPrecision == OUT_STROKE_PRECIS) { // Outline fonts only.
                std::string face_name(base::UTF16ToUTF8(lf.lfFaceName));
                font_families->push_back(face_name);
            }
        }
        return 1;
    }

    static int CALLBACK EnumFontsInFamilyProc(ENUMLOGFONTEXW* logical_font,
        NEWTEXTMETRICEXW* physical_font,
        DWORD font_type,
        LPARAM lparam)
    {
        FontDescList* fonts_in_family = reinterpret_cast<FontDescList*>(lparam);
        if (fonts_in_family) {
            const LOGFONTW& lf = logical_font->elfLogFont;
            if (lf.lfFaceName[0] && lf.lfFaceName[0] != '@' && lf.lfOutPrecision == OUT_STROKE_PRECIS) { // Outline fonts only.
                ppapi::proxy::SerializedTrueTypeFontDesc desc;
                desc.family = base::UTF16ToUTF8(lf.lfFaceName);
                if (lf.lfItalic)
                    desc.style = PP_TRUETYPEFONTSTYLE_ITALIC;
                desc.weight = static_cast<PP_TrueTypeFontWeight_Dev>(lf.lfWeight);
                desc.width = PP_TRUETYPEFONTWIDTH_NORMAL; // TODO(bbudge) support widths.
                desc.charset = static_cast<PP_TrueTypeFontCharset_Dev>(lf.lfCharSet);
                fonts_in_family->push_back(desc);
            }
        }
        return 1;
    }

} // namespace

void GetFontFamilies_SlowBlocking(FontFamilyList* font_families)
{
    LOGFONTW logfont;
    memset(&logfont, 0, sizeof(logfont));
    logfont.lfCharSet = DEFAULT_CHARSET;
    base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
    ::EnumFontFamiliesExW(hdc.Get(),
        &logfont,
        (FONTENUMPROCW)&EnumFontFamiliesProc,
        (LPARAM)font_families,
        0);
}

void GetFontsInFamily_SlowBlocking(const std::string& family,
    FontDescList* fonts_in_family)
{
    LOGFONTW logfont;
    memset(&logfont, 0, sizeof(logfont));
    logfont.lfCharSet = DEFAULT_CHARSET;
    base::string16 family16 = base::UTF8ToUTF16(family);
    // Copy the family name, leaving room for a terminating null (already set
    // since we zeroed the whole struct above.)
    family16.copy(logfont.lfFaceName, LF_FACESIZE - 1);
    base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
    ::EnumFontFamiliesExW(hdc.Get(),
        &logfont,
        (FONTENUMPROCW)&EnumFontsInFamilyProc,
        (LPARAM)fonts_in_family,
        0);
}

} // namespace content
